import { Injectable } from '@nestjs/common';
import { 
  ApiProvider, 
  TargetProvider, 
  GenericRequest, 
  GenericResponse,
  GenericMessage,
  GenericContentBlock,
  TokenManager
} from '../interfaces/api-adapter.interface';
import { BaseAdapter } from './base.adapter';
import { TokenManagerService } from '../services/token-manager.service';

/**
 * OpenAI API 到 Copilot API 的适配器
 * 演示如何轻松扩展支持新的 AI API
 */
@Injectable()
export class OpenAICopilotAdapter extends BaseAdapter {
  constructor(private readonly tokenManager: TokenManagerService) {
    super(ApiProvider.OPENAI, TargetProvider.COPILOT);
  }

  /**
   * 将 OpenAI 请求转换为通用格式
   */
  async convertToGeneric(openaiRequest: any): Promise<GenericRequest> {
    this.logConversion('OpenAI', 'Generic', { model: openaiRequest.model });

    const genericMessages: GenericMessage[] = openaiRequest.messages.map((msg: any) => ({
      role: msg.role,
      content: this.convertOpenAIContentToGeneric(msg.content)
    }));

    const genericRequest: GenericRequest = {
      model: openaiRequest.model,
      messages: genericMessages,
      max_tokens: openaiRequest.max_tokens,
      temperature: openaiRequest.temperature,
      top_p: openaiRequest.top_p,
      stream: openaiRequest.stream,
      metadata: {
        originalProvider: ApiProvider.OPENAI,
        openaiSpecific: {
          n: openaiRequest.n,
          stop: openaiRequest.stop,
          presence_penalty: openaiRequest.presence_penalty,
          frequency_penalty: openaiRequest.frequency_penalty
        }
      }
    };

    // 处理工具（OpenAI 称为 functions 或 tools）
    if (openaiRequest.tools && openaiRequest.tools.length > 0) {
      genericRequest.tools = openaiRequest.tools.map((tool: any) => ({
        name: tool.function.name,
        description: tool.function.description,
        input_schema: tool.function.parameters
      }));
    } else if (openaiRequest.functions && openaiRequest.functions.length > 0) {
      // 兼容旧的 functions 格式
      genericRequest.tools = openaiRequest.functions.map((func: any) => ({
        name: func.name,
        description: func.description,
        input_schema: func.parameters
      }));
    }

    return genericRequest;
  }

  /**
   * 将通用格式转换为 Copilot 请求格式
   */
  async convertFromGeneric(genericRequest: GenericRequest): Promise<any> {
    this.logConversion('Generic', 'Copilot', { model: genericRequest.model });

    const copilotMessages = genericRequest.messages.map(msg => ({
      role: msg.role,
      content: typeof msg.content === 'string' ? msg.content : this.extractTextContent(msg.content)
    }));

    const copilotRequest: any = {
      messages: copilotMessages,
      model: genericRequest.model,
      temperature: genericRequest.temperature || 0,
      top_p: genericRequest.top_p || 1,
      n: genericRequest.metadata?.openaiSpecific?.n || 1,
      max_tokens: genericRequest.max_tokens,
      stream: genericRequest.stream || false
    };

    // 处理 OpenAI 特有参数
    const openaiSpecific = genericRequest.metadata?.openaiSpecific;
    if (openaiSpecific) {
      if (openaiSpecific.stop) copilotRequest.stop = openaiSpecific.stop;
      if (openaiSpecific.presence_penalty) copilotRequest.presence_penalty = openaiSpecific.presence_penalty;
      if (openaiSpecific.frequency_penalty) copilotRequest.frequency_penalty = openaiSpecific.frequency_penalty;
    }

    // 处理工具
    if (genericRequest.tools && genericRequest.tools.length > 0) {
      copilotRequest.tools = genericRequest.tools.map(tool => ({
        type: 'function',
        function: {
          name: tool.name,
          description: tool.description,
          parameters: tool.input_schema
        }
      }));
    }

    return copilotRequest;
  }

  /**
   * 解析 Copilot 响应为通用格式
   */
  async parseTargetResponse(copilotResponse: any, originalRequest?: any): Promise<GenericResponse> {
    this.logConversion('Copilot', 'Generic', { id: copilotResponse.id });

    if (!copilotResponse.choices || copilotResponse.choices.length === 0) {
      throw new Error('No choices in Copilot response');
    }

    const choice = copilotResponse.choices[0];
    const content: GenericContentBlock[] = [];

    // 处理普通文本内容
    if (choice.message.content) {
      content.push({
        type: 'text',
        text: choice.message.content
      });
    }

    // 处理工具调用
    if (choice.message.tool_calls) {
      choice.message.tool_calls.forEach((toolCall: any) => {
        content.push({
          type: 'tool_use',
          name: toolCall.function.name,
          input: JSON.parse(toolCall.function.arguments),
          tool_use_id: toolCall.id
        });
      });
    }

    return {
      id: copilotResponse.id,
      model: copilotResponse.model,
      content,
      stop_reason: this.mapStopReason(choice.finish_reason),
      usage: {
        input_tokens: copilotResponse.usage?.prompt_tokens || 0,
        output_tokens: copilotResponse.usage?.completion_tokens || 0,
        total_tokens: copilotResponse.usage?.total_tokens || 0
      },
      metadata: {
        originalTarget: TargetProvider.COPILOT,
        copilotModel: copilotResponse.model
      }
    };
  }

  /**
   * 将通用响应转换为 OpenAI 格式
   */
  async convertToSourceResponse(genericResponse: GenericResponse, originalRequest?: any): Promise<any> {
    this.logConversion('Generic', 'OpenAI', { id: genericResponse.id });

    // 提取文本内容
    const textContent = genericResponse.content
      .filter(block => block.type === 'text')
      .map(block => block.text)
      .join('');

    // 提取工具调用
    const toolCalls = genericResponse.content
      .filter(block => block.type === 'tool_use')
      .map(block => ({
        id: block.tool_use_id || this.generateRequestId(),
        type: 'function',
        function: {
          name: block.name,
          arguments: JSON.stringify(block.input)
        }
      }));

    const message: any = {
      role: 'assistant',
      content: textContent || null
    };

    if (toolCalls.length > 0) {
      message.tool_calls = toolCalls;
    }

    return {
      id: genericResponse.id,
      object: 'chat.completion',
      created: Math.floor(Date.now() / 1000),
      model: genericResponse.model,
      choices: [{
        index: 0,
        message,
        finish_reason: this.mapStopReasonToOpenAI(genericResponse.stop_reason)
      }],
      usage: {
        prompt_tokens: genericResponse.usage.input_tokens,
        completion_tokens: genericResponse.usage.output_tokens,
        total_tokens: genericResponse.usage.total_tokens
      }
    };
  }

  /**
   * 获取请求头部
   */
  async getRequestHeaders(config: any): Promise<Record<string, string>> {
    const validToken = await this.tokenManager.getValidToken();
    
    return {
      'authorization': `Bearer ${validToken}`,
      'content-type': 'application/json',
      'user-agent': config.userAgent || 'OpenAI-API-Client/1.0.0',
      'x-request-id': this.generateRequestId()
    };
  }

  /**
   * 获取目标端点
   */
  getTargetEndpoint(operation: string): string {
    return `/chat/completions`;
  }

  /**
   * 获取 Token 管理器
   */
  getTokenManager(): TokenManager {
    return this.tokenManager;
  }

  /**
   * 获取必需字段
   */
  protected getRequiredFields(): string[] {
    return ['model', 'messages'];
  }

  /**
   * 转换 OpenAI 内容为通用格式
   */
  private convertOpenAIContentToGeneric(content: any): string | GenericContentBlock[] {
    if (typeof content === 'string') {
      return content;
    }

    if (Array.isArray(content)) {
      return content.map(block => {
        switch (block.type) {
          case 'text':
            return {
              type: 'text' as const,
              text: block.text
            };
          case 'image_url':
            return {
              type: 'image' as const,
              source: block.image_url
            };
          default:
            return {
              type: 'text' as const,
              text: String(block.text || '')
            };
        }
      });
    }

    return String(content);
  }


  /**
   * 停止原因映射：通用 -> OpenAI
   */
  private mapStopReasonToOpenAI(stopReason: string): string {
    const stopReasonMap: Record<string, string> = {
      'end_turn': 'stop',
      'max_tokens': 'length',
      'tool_use': 'tool_calls',
      'refusal': 'content_filter'
    };

    return stopReasonMap[stopReason] || 'stop';
  }
}